﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcControlToolkit
{
    /// <summary>
    /// The AlwaysVisibleControl is a simple extender allowing you to pin controls 
    /// to the page so that they appear to float over the background body content 
    /// when it is scrolled or resized. It targets any ASP.NET control and always 
    /// keeps the position a specified distance from the desired horizontal and 
    /// vertical sides.<br/>
    /// To avoid having the control flash and move when the page loads, it is 
    /// recommended that you absolutely position the control in the desired location 
    /// in addition to attaching the extender. 
    /// </summary>
    public static class AlwaysVisibleControlExtensions
    {
        private static readonly int DEFAULT_OFFSET = 0;
        private static readonly HorizontalSide DEFAULT_HORIZONTAL_SIDE = HorizontalSide.Left;
        private static readonly VerticalSide DEFAULT_VERTICAL_SIDE = VerticalSide.Top;
        private static readonly float DEFAULT_SCROLL_DURATION = 0.1f;

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the default property values
        /// </summary>
        /// <remarks>
        /// Offset x and y will be set to their default: 0 pixels<br/>
        /// Horizontal edge will be set to Left, Vertical Edge will be set to top<br/>
        /// ScrollEffectDuration will be set to 0.1 seconds
        /// </remarks>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId)
        {
            return helper.AlwaysVisibleControl(elementId, DEFAULT_SCROLL_DURATION);
        }

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the specified properties
        /// </summary>
        /// <remarks>
        /// Offset x and y will be set to their default: 0 pixels<br/>
        /// Horizontal edge will be set to Left, Vertical Edge will be set to top
        /// </remarks>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        /// <param name="scrollEffectDuration">Length in seconds of the scrolling effect to last when the target control is repositioned. The default is .1 second</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId, float scrollEffectDuration)
        {
            return helper.AlwaysVisibleControl(elementId, DEFAULT_HORIZONTAL_SIDE, DEFAULT_VERTICAL_SIDE, scrollEffectDuration);
        }

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the specified properties
        /// </summary>
        /// <remarks>
        /// Offset x and y will be set to their default: 0 pixels<br/>
        /// ScrollEffectDuration will be set to 0.1 seconds
        /// </remarks>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        /// <param name="hSide">Horizontal edge of the browser (either Left, Center, or Right) used to anchor the target control. The default is Left</param>
        /// <param name="vSide">Vertical edge of the browser (either Top, Middle, or Bottom) used to anchor the target control. The default is Top</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId, HorizontalSide hSide, VerticalSide vSide)
        {
            return helper.AlwaysVisibleControl(elementId, hSide, vSide, DEFAULT_SCROLL_DURATION);
        }

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the specified properties
        /// </summary>
        /// <remarks>Offset x and y will be set to their default: 0 pixels</remarks>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        /// <param name="hSide">Horizontal edge of the browser (either Left, Center, or Right) used to anchor the target control. The default is Left</param>
        /// <param name="vSide">Vertical edge of the browser (either Top, Middle, or Bottom) used to anchor the target control. The default is Top</param>
        /// <param name="scrollEffectDuration">Length in seconds of the scrolling effect to last when the target control is repositioned. The default is .1 second</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId, HorizontalSide hSide, VerticalSide vSide, float scrollEffectDuration)
        {
            return helper.AlwaysVisibleControl(elementId, hSide, vSide, DEFAULT_OFFSET, DEFAULT_OFFSET, scrollEffectDuration);
        }

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the specified properties
        /// </summary>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        /// <param name="hSide">Horizontal edge of the browser (either Left, Center, or Right) used to anchor the target control. The default is Left</param>
        /// <param name="vSide">Vertical edge of the browser (either Top, Middle, or Bottom) used to anchor the target control. The default is Top</param>
        /// <param name="horizontalOffset">Distance to the HorizontalSide edge of the browser in pixels from the same side of the target control. The default is 0 pixels</param>
        /// <param name="verticalOffset">Distance to the VerticalSide edge of the browser in pixels from the same side of the target control. The default is 0 pixels</param>
        /// <param name="scrollEffectDuration">Length in seconds of the scrolling effect to last when the target control is repositioned. The default is .1 second</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId, HorizontalSide hSide, VerticalSide vSide, int horizontalOffset, int verticalOffset, float scrollEffectDuration)
        {
            RouteValueDictionary props = new RouteValueDictionary();
            props.AddIfNotEqual("HorizontalSide", hSide, DEFAULT_HORIZONTAL_SIDE);
            props.AddIfNotEqual("VerticalSide", vSide, DEFAULT_VERTICAL_SIDE);
            props.AddIfNotEqual("HorizontalOffset", horizontalOffset, DEFAULT_OFFSET);
            props.AddIfNotEqual("VerticalOffset", verticalOffset, DEFAULT_OFFSET);
            props.AddIfNotEqual("ScrollEffectDuration", scrollEffectDuration, DEFAULT_SCROLL_DURATION);

            return helper.AlwaysVisibleControl(elementId, props);
        }

        /// <summary>
        /// Creates and AlwaysVisibleControl Extender with the specified properties
        /// </summary>
        /// <param name="elementId">ID of control for this extender to always make visible</param>
        /// <param name="properties">An object containing the properties for this extender</param>
        public static string AlwaysVisibleControl(this AjaxHelper helper, string elementId, object properties)
        {
            var sb = new StringBuilder();

            // Add Microsoft Ajax library   
            sb.Append(helper.MicrosoftAjaxInclude());

            // Add toolkit scripts   
            sb.Append(helper.ToolkitInclude(
                    "AjaxControlToolkit.ExtenderBase.BaseScripts.js",
                    "AjaxControlToolkit.Common.Common.js",
                    "AjaxControlToolkit.Compat.Timer.Timer.js",
                    "AjaxControlToolkit.Animation.Animations.js",
                    "AjaxControlToolkit.AlwaysVisibleControl.AlwaysVisibleControlBehavior.js"
                ));

            // Perform $create               
            sb.AppendLine(helper.Create("AjaxControlToolkit.AlwaysVisibleControlBehavior", properties, elementId));

            return sb.ToString();
        }
    }

    #region [Enumerations]

    public enum VerticalSide
    {
        Top = 0,
        Middle = 1,
        Bottom = 2
    }

    public enum HorizontalSide
    {
        Left = 0,
        Center = 1,
        Right = 2
    }

    #endregion
}
